﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.IO;
using System.Windows.Markup;
using System.Threading;
using System.Windows.Navigation;
using System.Windows.Data;
using PasswordProvider.View.Properties;

namespace PasswordProvider.View
{
    /// <summary>
    /// Interaction logic for HelpReader.xaml
    /// </summary>
    public sealed partial class HelpReader : Window
    {
        private const string _helpFilePath = "Help/Help.xaml";
        
        private FlowDocumentPageViewer _viewer;
        private Frame _frame;
        private ListBox _contentsListBox;

        /// <summary>
        /// The ReallyLoaded event is raised when the page is loaded and the contained Navigation 
        /// Frame has completed navigating to its initial contents. 
        /// </summary>
        public event EventHandler ReallyLoaded;

        public HelpReader()
        {            
            InitializeComponent();
           // Topmost = Settings.Default.AlwaysOnTop || Settings.Default.RunInSystemTray;           
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _viewer = (FlowDocumentPageViewer)Template.FindName("_viewer", this);
            _frame = (Frame)Template.FindName("_frame", this);
            _contentsListBox = (ListBox)Template.FindName("_contentsListBox", this);
            _contentsListBox.SizeChanged += new SizeChangedEventHandler(_contentsListBox_SizeChanged);
            _contentsListBox.SelectionChanged += new SelectionChangedEventHandler(_contentsListBox_SelectionChanged);

            _viewer.Document = OpenDocument();

            // Declare the handler, then assign it. Otherwise the compiler compains about use of unassigned variable.
            NavigatedEventHandler handler = null;
            handler = delegate
            {
                // First remove the delegate from the Navigated event, to prevent infinite loop and stack overflow.
                _frame.Navigated -= handler;
                // Raise the ReallyLoaded event.
                if (ReallyLoaded != null)
                    ReallyLoaded(this, new EventArgs());
            };
            // Add the event handler to the frame's Navigated event.
            _frame.Navigated += handler;

            // Create a second event handler to peforem navitagion to default web browser
            // when a Hyperlink 
            _frame.Navigating += new NavigatingCancelEventHandler(_frame_Navigating);
        }

        void _frame_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            string uri = e.Uri.ToString();
            if (uri.StartsWith("http:", true, null))
            {
                System.Diagnostics.Process.Start(e.Uri.ToString());
                e.Cancel = true;
            }
        }

        #region Public Methods

        /// <summary>
        /// Method to go to a specific section in the flow document.
        /// </summary>
        /// <param name="targetSection">The Name of the target section</param>
        public void GoTo(string targetSection)
        {
            string name = targetSection;
            if(String.IsNullOrEmpty(name))
                name = (_viewer.Document as FlowDocument).Blocks.FirstBlock.Name;
            Uri uri = new Uri("#" + name, UriKind.RelativeOrAbsolute);

            bool removeBackEntry = _frame.NavigationService.Source == null;
            _frame.Navigate(uri);
            if (removeBackEntry)
                _frame.NavigationService.RemoveBackEntry();
            
        }

        

        #endregion

        #region Event Handlers

        private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
        {
            double x = Width + e.HorizontalChange;
            double y = Height + e.VerticalChange;
            if (x > 0)
                Width = x;
            if (y > 0)
                Height = y;
        }

        private void HandleDragRequest(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
                DragMove();
        }

        private void HandleCloseRequest(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void _contentsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBoxItem selected = _contentsListBox.SelectedItem as ListBoxItem;
            if (selected != null)
                GoTo(selected.Tag as string);
        }

        private void _contentsListBox_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // Set focus on the contents list box when it is made visible, makes behavior more intuitive.
            if (e.NewSize.Height > 0)
                _contentsListBox.Focus();
        }

        private void _navigateBackButton_Click(object sender, RoutedEventArgs e)
        {
            if (_frame.CanGoBack)
            {
                _frame.GoBack();
            }
        }

        private void _navigateForwardButton_Click(object sender, RoutedEventArgs e)
        {
            if (_frame.CanGoForward)
                _frame.GoForward();
        }

        #endregion

        #region Private Methods

        private static FlowDocument OpenDocument()
        {            
            // Open the file that contains the FlowDocument...
            using (FileStream xamlFile = new FileStream(_helpFilePath, FileMode.Open, FileAccess.Read))
            {
                FlowDocument content = XamlReader.Load(xamlFile) as FlowDocument;                
                return content;
            }
        }

        

        #endregion

 
        
    }

    /// <summary>
    /// Convert a bool value to the Visibility enum.
    /// </summary>
    class BoolToVisibilityEnumValueConverter : IValueConverter
    {
        #region IValueConverter Members

        object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            // convert from bool to visibility
            if ((bool)value)
            {
                return System.Windows.Visibility.Visible;
            }
            else
            {
                if (parameter != null)
                {
                    return (Visibility)Enum.Parse(typeof(Visibility), (string)parameter);
                }
                else
                    return Visibility.Hidden;
            }
        }
        // Convert from visibility to bool
        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (Visibility)value == Visibility.Visible ? true : false;
        }

        #endregion

    }

}
